package com.gitee.feizns.convert;

import com.gitee.feizns.convert.method.MethodConverter;
import com.gitee.feizns.convert.impl.DateConverter;
import com.gitee.feizns.convert.impl.NumberConverter;
import com.gitee.feizns.convert.method.valueof.SingleParameterValueOfConverter;
import com.gitee.feizns.convert.method.valueof.TwoParametersValueOfConverter;

import java.util.Comparator;
import java.util.TreeSet;

/**
 * @author feizns
 * @since 2019/5/19 0019
 */
public abstract class ConvertUtils {

    /**
     * 常规转换器
     */
    private static final TreeSet<Converter> COMMONS_CONVERTERS = new TreeSet<>(priority());

    /**
     * 方法转换器
     */
    private static final TreeSet<Converter> METHOD_CONVERTERS = new TreeSet<>(priority());

    static {
        registry(new NumberConverter());
        registry(new DateConverter());
        registry(new SingleParameterValueOfConverter());
        registry(new TwoParametersValueOfConverter());
    }

    public static <T> T to(Object original, Class<T> targetType){
        if ( COMMONS_CONVERTERS.stream().anyMatch(converter -> converter.support(targetType)) ) {
            return to(COMMONS_CONVERTERS, original, targetType);
        } else {
            return (T) to(METHOD_CONVERTERS, original, PrimitiveUtils.getWrapper(targetType));
        }
    }

    /**
     * 任意类型转换
     * @param converters
     * @param original
     * @param targetType
     * @return
     */
    private static <T> T to(TreeSet<Converter> converters, Object original, Class<T> targetType) {
        for (Converter converter : converters) {
            if ( converter.support(targetType) ) {
                Object result = converter.to(original, targetType);
                if ( result != null )
                    return (T) result;
            }
        }
        return null;
    }

    /**
     * 注册转换器
     * @param converter
     */
    public static final void registry(Converter converter) {
        if ( converter instanceof MethodConverter ) {
            MethodConverter methodConverter = (MethodConverter) converter;
            methodConverter.setConverters(COMMONS_CONVERTERS);
            METHOD_CONVERTERS.add(methodConverter);
        } else {
            COMMONS_CONVERTERS.add(converter);
        }
    }

    /**
     * 排序规则
     * @return
     */
    private static final Comparator<? super Converter> priority() {
        return (o1, o2) -> o1.priority() < o2.priority() ? -1 : 1;
    }

}
